package com.dzqd.ecop.crm.sim;

import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.Provider;
import javax.xml.ws.Service;
import javax.xml.ws.ServiceMode;
import javax.xml.ws.WebServiceProvider;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

@WebServiceProvider
@ServiceMode(value = Service.Mode.MESSAGE)
public class CrmSimulator implements Provider<SOAPMessage> {

	protected CrmSimulatorLogger logger;

	DocumentBuilder builder;

	File responseMassageDirctory;

	public CrmSimulator() throws SimulationException {
		logger = new SystemOutLogger();

		URL responseMassageResource = this.getClass().getClassLoader().getResource("rsp-msg");
		logger.info("responseMassageResource=" + responseMassageResource.getPath());
		responseMassageDirctory = new File(responseMassageResource.getPath());

		DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
		try {
			builder = builderFactory.newDocumentBuilder();
		} catch (ParserConfigurationException e) {
			throw new SimulationException("初始化失败!", e);
		}
	}

	@Override
	public SOAPMessage invoke(SOAPMessage request) {

		try {
			String processCode = parseProcessCodeFrom(request);

			SOAPMessage response = generateResponse(processCode);

			write(response);

			return response;

		} catch (Exception e) {
			e.printStackTrace();
		}

		return null;
	}

	private void write(SOAPMessage response) throws SOAPException, IOException {
		System.out.println("response message:");
		response.writeTo(System.out);
		System.out.println();
	}

	private SOAPMessage generateResponse(String processCode) throws Exception {

		File headerFile = findHeaderResponseXmlFile(processCode);

		File bodyfile = findBodyResponseXmlFile(processCode);

		FileInputStream headerInputStream = null;
		FileInputStream bodyInputStream = null;
		Document document = null;
		try {
			headerInputStream = new FileInputStream(headerFile);
			bodyInputStream = new FileInputStream(bodyfile);

			HeaderAndBodyResponseMerger merger = new HeaderAndBodyResponseMerger(processCode + "rsp");
			document = merger.merge(headerInputStream, bodyInputStream);
		} finally {
			if (headerInputStream != null)
				headerInputStream.close();
			if (bodyInputStream != null) {
				bodyInputStream.close();
			}
		}

		//生成SOAPMessage
		SOAPMessage response = MessageFactory.newInstance().createMessage();
		SOAPBody responseBody = response.getSOAPBody();

		responseBody.addDocument(document);

		response.saveChanges();
		return response;
	}

	private String parseProcessCodeFrom(SOAPMessage request) throws SOAPException, SimulationException {
		SOAPBody soapBody = request.getSOAPBody();
		Node headerNode = soapBody.getFirstChild().getFirstChild();
		NodeList childNodes = headerNode.getChildNodes();
		if (childNodes.getLength() < 1) {
			throw new SimulationException("头部节点没有内容！");
		}
		String processCode = null;
		for (int i = 0; i < childNodes.getLength(); i++) {
			Node item = childNodes.item(i);
			String nodeName = item.getNodeName();
			if ("process_code".equals(nodeName)) {
				processCode = item.getTextContent().trim();
			}
		}
		if (processCode == null) {
			throw new SimulationException("请求报文头部找不到process_code节点！");
		}
		return processCode;
	}

	private File findHeaderResponseXmlFile(String processCode) throws FileNotFoundException, SimulationException {
		final String fileNamePatter = "_" + processCode + "_header.xml";
		File headerDirctory = new File(responseMassageDirctory.getPath() + File.separator + "header");
		return getSingleFileByEndWithName(headerDirctory, fileNamePatter);
	}

	private File findBodyResponseXmlFile(final String processCode) throws FileNotFoundException, SimulationException {
		final String fileNamePatter = "_" + processCode + ".xml";
		return getSingleFileByEndWithName(responseMassageDirctory, fileNamePatter);
	}

	private File getSingleFileByEndWithName(File responseMassageDirctory, final String fileNamePatter)
			throws FileNotFoundException, SimulationException {
		logger.info("responseMassageDirctory=" + responseMassageDirctory.getPath() + "~fileNamePatter=" + fileNamePatter);

		FileFilter fileFilter = new FileFilter() {
			@Override
			public boolean accept(File pathname) {
				return pathname.getName().endsWith(fileNamePatter);
			}
		};
		File[] files = responseMassageDirctory.listFiles(fileFilter);
		if (files.length == 0) {
			throw new FileNotFoundException("未能找到响应报文文件！");
		}
		if (files.length > 1) {
			throw new SimulationException("找到多个匹配的响应报文文件: *" + fileNamePatter);
		}
		File bodyfile = files[0];

		return bodyfile;
	}

}
